# -*- coding: utf-8 -*-
'''
@文件    :database.py
@说明    :数据库初始化操作
@时间    :2025/08/26 15:47:14
@作者    :浪晋
@版本    :1.0
'''
import time
import json
from types import SimpleNamespace
from fastapi import UploadFile
from fastapi.requests import Request
from fastapi.routing import APIRoute
from fastapi.responses import Response, JSONResponse, FileResponse
from app.core.plugin import database
from app.services.system.user import service as user_service
from app.services.system.menu import service as menu_service
from app.services.system.dept import service as dept_service
from app.services.system.role import service as role_service
from app.services.monitor.log import service as log_service
from app.schemas.monitor.log import CreateSchema as LogCreateSchema
from app.core.logger import logger
from app.settings.config import config


async def init_database_data():
    """初始化数据库数据"""
    await database.startup()
    await menu_service.init_menu_data()
    await dept_service.init_dept_data()
    await role_service.init_role_data()
    await user_service.init_user_data()
    logger.info("初始化database缓存数据")


async def close_database_data():
    """关闭数据库"""
    await database.shutdown()
    logger.info("关闭database缓存数据")


async def record_request_log(request: Request, response: Response, errorlog: str = None):
    """记录请求日志"""
    request_id = request.scope.get("request_id")
    response.headers['x-request-id'] = request_id
    if config.IGNORE_OPERATION_LOG:
        return response
    route: APIRoute = request.scope.get("route") or SimpleNamespace(name="404_not_found", endpoint="404_not_found", summary="404_not_found")
    endpoint = route.endpoint
    func_name = endpoint.__name__ if endpoint != '404_not_found' else endpoint
    if func_name in config.IGNORE_OPERATION_FUNCTION:
        return response
    name = route.name
    summary = route.summary
    url = request.url
    path = request.url.path
    method = request.method
    headers = json.dumps(dict(request.headers))
    client_ip = request.headers.get('X-Real-Ip') or request.client.host
    api_key = request.headers.get(config.SECURITY_HEADER_NAME,"未登录")
    payload = {}
    try:
        payload = await request.json()
    except:
        form_data  = await request.form()
        for key in form_data:
            values = form_data.getlist(key)
            if len(values) == 1:
                value = values[0]
                if isinstance(value, UploadFile):
                    payload[key] = value.filename
                else:
                    payload[key] = value
            else:
                payload[key] = values
    finally:
        payload.update(dict(request.query_params))
    status_code = response.status_code
    if isinstance(response, JSONResponse):
        result = json.loads(response.body.decode())
    elif isinstance(response, FileResponse):
        result = {
            "filename": response.filename,
            "media_type": response.media_type
        }
    else:
        result = {"message": f"{type(response).__name__}类型不支持记录"}
    end_time = time.perf_counter()
    process_time = f'{end_time- request.scope["start_time"]:.4f}s'
    response.headers['x-process-time'] = process_time
    if config.LOGGER_OUTPUT_CONSOLE:
        logger.info(f"请求编号: {request_id}")
        logger.info(f"请求名称: {name}")
        logger.info(f"请求名称: {func_name}")
        logger.info(f"请求介绍: {summary}")
        logger.info(f"请求路径: {path}")
        logger.info(f"请求地址: {url}")
        logger.info(f"请求方法: {method}")
        logger.info(f"请求来源：{client_ip}")
        logger.info(f"请 求 头: {api_key}")
        logger.info(f"请求参数: {payload}")
        logger.info(f"状 态 码: {status_code}")
        logger.info(f"响应时间: {process_time}")
        logger.info(f"响应结果: {result}")
        if errorlog:
            logger.error(f"错误日志: {errorlog}")
    if config.LOGGER_OUTPUT_DATABASE:
        log = LogCreateSchema(
            request_id=request_id,
            summary=summary,
            url=str(url),
            method=method,
            client_ip=client_ip,
            payload=payload,
            headers=headers,
            result=result,
            status_code=status_code,
            process_time=process_time,
            error_log=errorlog
        )
        await log_service.create(log)
    return response
